﻿using System;
using System.Collections.Generic;
 
using System.Text;
using System.Threading;
using System.IO;
using GGSharp.Packets;

namespace GGSharp
{
    public class GGReceiver : IDisposable
    {
        protected const int SLEEPTIME = 250;

        protected GGConnection _connection;
        protected BinaryReader _reader;
        protected Thread _thread;

        public delegate void PacketReceivedDelegate(object sender, HeaderPacket packet);
        public event PacketReceivedDelegate PacketReceived;

        public GGReceiver(GGConnection connection)
        {
            _connection = connection;
            _connection.Connected += _connection_Connected;
            _thread = new Thread(new ThreadStart(checkAndProcessQueue));   // towrzymy nowy watek
            _thread.IsBackground = true;
        }

        void _connection_Connected(object sender, EventArgs e)
        {
            _reader = new BinaryReader(_connection.Stream);
            _thread.Start(); // uruchamiamy watek
            _connection.Connected -= _connection_Connected;
            _connection.Disconnected += _connection_Disconnected;
        }

        void _connection_Disconnected(object sender, EventArgs e)
        {
            _thread.Abort();
            _reader = null;
            _connection.Connected += _connection_Connected;
            _connection.Disconnected -= _connection_Disconnected;
        }

        public virtual void OnPackedReceived(HeaderPacket packet)
        {
            if (PacketReceived != null)
                PacketReceived(this, packet);
        }

        private void checkAndProcessQueue()
        {
            try
            {
                while (true)
                {
                    //jesli NIE jest dostepny header to czekaj dalej
                    if (!_connection.IsConnected || _connection.Socket.Available < 8)
                    {
                        Thread.Sleep(SLEEPTIME);
                        continue;
                    }

                    int type = _reader.ReadInt32();
                    Packets.HeaderPacket packet = GGPacketFactory.Get(type);
                    packet.Read(_reader);
                    OnPackedReceived(packet);
                }
            }
            catch (ThreadAbortException e) { }
            catch (Exception e) { _connection.Disconnect(); }
        }

        #region IDisposable Members

        public void Dispose()
        {
            _connection = null;
        }

        #endregion
    }
}
